package com.ywcq.netty.httpserver.codec;

import static io.netty.handler.codec.http.HttpConstants.CR;
import static io.netty.handler.codec.http.HttpConstants.LF;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

/**
 * 测试最简单HTTP请求的性能：总耗时在3ms至15ms直接（360浏览器测试，访问地址：http://localhost:8601/）
 * 多数请求在3ms左右
 * 总耗时2ms(Request sent：0.389，Waiting (TTFB)：0.831ms，Content Download: 0.454ms， Explanation：2.942ms)
 * 
 * 
 * 总耗时13ms(Request sent：0.232，Waiting (TTFB)：2.833ms，Content Download: 5.536ms， Explanation：15.564ms)
 * 
 * 比较两次时间，主要差别在content download时间，内容下载时间越长，浏览器解释时间也越长。
 * @author luozhen
 *
 */
public class HttpSimpleInboundHandler 
extends ChannelInboundHandlerAdapter 
{
	
	 static final byte[] CRLF = { CR, LF };
	 
	 static byte[] firstLine = "HTTP/1.1 200 OK".getBytes();
	 
	 static byte[] header1 = "Content-Type: text/plain".getBytes();
	 static byte[] header2 = "Content-Length: 11".getBytes();
	 static byte[] header3 = "Connection: keep-alive".getBytes();
	 //回车换行
	 static byte[] sp = {13,10};
	 //HTTP响应体和响应头直接有2个回车换行
	 static byte[] bodycontent = "Hello Netty".getBytes();
	 
	 static byte[] httpRspContent = {72, 84, 84, 80, 47, 49, 46, 49, 32, 50, 48, 48, 32, 79, 75, 13, 10, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 13, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 49, 49, 13,10,67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 58, 32, 107, 101, 101, 112, 45, 97, 108, 105, 118, 101,13, 10, 13, 10,72, 101, 108, 108, 111, 32, 78, 101, 116, 116, 121};
	 
	 static ByteBuf directBuf = Unpooled.directBuffer();
	 
	 static {
		 
		 directBuf.writeBytes(firstLine).writeBytes(sp)
		 .writeBytes(header1).writeBytes(sp)
		 .writeBytes(header2).writeBytes(sp)
		 .writeBytes(header3).writeBytes(sp).writeBytes(sp).writeBytes(bodycontent);
	 }

	 @Override
	 public void channelReadComplete(ChannelHandlerContext ctx) 
	 {
	        ctx.flush();
	 }
	 
	 @Override
	    public void channelRead(ChannelHandlerContext ctx, Object msg) {
	    	ReferenceCountUtil.release(msg);
	    	//HTTP/1.1 200 OK\r\n
	    	ctx.write(directBuf.copy());
	    	ctx.flush();
	    }

	    public void channelReadback(ChannelHandlerContext ctx, Object msg) {
	    	ReferenceCountUtil.release(msg);
	    	//HTTP/1.1 200 OK\r\n
	    	byte[] content = {72, 84, 84, 80, 47, 49, 46, 49, 32, 50, 48, 48, 32, 79, 75, 13, 10};
	    	
////			Content-Type: text/plain'\r\n'
////			Content-Length: 11'\r\n'
////			Connection: keep-alive'\r\n'
////			13, 10,72, 101, 108, 108, 111, 32, 78, 101, 116, 116, 121
//	    	ByteBuf buf = ctx.alloc().buffer();
	    	ByteBuf buf = ctx.alloc().directBuffer();
	    	buf.writeBytes(content);
	    	byte[] temp = "Content-Type: text/plain".getBytes();
	    	//67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110
	    	System.out.println("");
	    	for (byte b : temp)
	    	{
	    		System.out.print(b);
	    		System.out.print(", ");
	    	}
	    	//67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 49, 49
	    	temp = "Content-Length: 11".getBytes();
	    	System.out.println("");
	    	for (byte b : temp)
	    	{
	    		System.out.print(b);
	    		System.out.print(", ");
	    	}
	    	
	    	temp = "Connection: keep-alive".getBytes();
	    	System.out.println("");
	    	for (byte b : temp)
	    	{
	    		System.out.print(b);
	    		System.out.print(", ");
	    	}
	    			
	    	//67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 58, 32, 107, 101, 101, 112, 45, 97, 108, 105, 118, 101
	    	buf.writeBytes("Content-Type: text/plain".getBytes());
	    	buf.writeBytes(sp);
	    	buf.writeBytes("Content-Length: 11".getBytes());
	    	buf.writeBytes(sp);
	    	buf.writeBytes("Connection: keep-alive".getBytes());
	    	buf.writeBytes(sp);
	    	buf.writeBytes(sp);
	    	buf.writeBytes(bodycontent);
	    	ctx.write(buf);
	    	ctx.flush();
	    }
}
